/*
 * Copyright (c) 2020-2021 imlzw@vip.qq.com jweb.cc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package cc.jweb.adai.web.system.generator.controller;

import cc.jweb.adai.web.system.file.model.SysFile;
import cc.jweb.adai.web.system.generator.model.GeneratorModel;
import cc.jweb.adai.web.system.generator.model.TemplateModel;
import cc.jweb.adai.web.system.generator.service.CodeGenerator;
import cc.jweb.adai.web.system.generator.service.WebServerService;
import cc.jweb.adai.web.system.log.service.SysLogService;
import cc.jweb.adai.web.system.sys.model.SysLog;
import cc.jweb.adai.web.system.sys.service.FileService;
import cc.jweb.boot.common.exception.ParameterValidationException;
import cc.jweb.boot.common.lang.Result;
import cc.jweb.boot.controller.JwebController;
import cc.jweb.boot.db.Db;
import cc.jweb.boot.security.annotation.Logical;
import cc.jweb.boot.security.annotation.RequiresPermissions;
import cc.jweb.boot.security.session.account.JwebSecurityAccount;
import cc.jweb.boot.security.utils.JwebSecurityUtils;
import cc.jweb.boot.utils.compress.ZipUtils;
import cc.jweb.boot.utils.file.FileUtils;
import cc.jweb.boot.utils.lang.IDGenerator;
import cc.jweb.boot.utils.lang.ResponseUtils;
import cc.jweb.boot.utils.lang.StringUtils;
import cc.jweb.boot.utils.lang.collection.MapUtils;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import com.jfinal.core.NotAction;
import com.jfinal.kit.PathKit;
import com.jfinal.kit.StrKit;
import com.jfinal.render.Render;
import com.jfinal.upload.UploadFile;
import io.jboot.web.controller.annotation.RequestMapping;

import javax.servlet.ServletOutputStream;
import java.io.*;
import java.nio.charset.Charset;
import java.nio.file.NoSuchFileException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static cn.hutool.core.util.StrUtil.compareVersion;

@RequiresPermissions("system:generator:temp:view")
@RequestMapping(value = "/generator/template", viewPath = "/WEB-INF/views/generator/template")
public class TemplateModelController extends JwebController {

    final static Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create();

    public void index() {
        render("index2.html");
    }

    /**
     * 编辑页面
     */
    @RequiresPermissions("system:generator:temp:edit")
    public void editPage() {
        String id = getPara("template_id");
        TemplateModel templateModel = null;
        if (id != null) {
            templateModel = TemplateModel.dao.findById(id);
            if (templateModel == null) {
                templateModel = new TemplateModel();
            }
        }
        if (templateModel == null) {
            templateModel = new TemplateModel();
        }
        setAttr("detail", templateModel);
        render("edit.html");
    }

    /**
     * 详情页
     */
    public void detailPage() {
        String id = getPara("template_id");
        TemplateModel templateModel = null;
        if (id != null) {
            templateModel = TemplateModel.dao.findById(id);
        }
        if (templateModel == null) {
            templateModel = new TemplateModel();
        }
        setAttr("detail", templateModel);
        render("detail.html");
    }

    /**
     * 复制模板页面
     */
    public void copyPage() {
        String id = getPara("template_id");
        TemplateModel templateModel = null;
        if (id != null) {
            templateModel = TemplateModel.dao.findById(id);
        }
        if (templateModel == null) {
            templateModel = new TemplateModel();
        }
        setAttr("detail", templateModel);
        render("copy.html");
    }

    /**
     * 代码生成页面
     */
    public void generatePage() {
        String id = getPara("template_id");
        TemplateModel templateModel = null;
        if (id != null) {
            templateModel = TemplateModel.dao.findById(id);
        }
        if (templateModel == null) {
            renderHtml("<div class=\"template_error_info\">模板不存在！</div>");
            return;
        }
        setAttr("detail", templateModel);
        render("generate.html");
    }

    /**
     * 选择生成器页面
     */
    public void selectGeneratorPage() {
        String id = getPara("template_id");
        String gid = getPara("generator_id");
        TemplateModel templateModel = null;
        if (id != null) {
            templateModel = TemplateModel.dao.findById(id);
        }
        if (templateModel == null) {
            templateModel = new TemplateModel();
        }
        setAttr("detail", templateModel);
        setAttr("generatorId", gid);
        render("selectGenerator.html");
    }

    /**
     * 编辑生成器页面
     */
    public void editGeneratorPage() {
        String templateId = getPara("template_id");
        String generatorId = getPara("generator_id");
        TemplateModel templateModel = null;
        if (templateId != null) {
            templateModel = TemplateModel.dao.findById(templateId);
        }
        if (templateModel == null) {
            renderHtml("<div class=\"template_error_info\">模板不存在！<div>");
            return;
        }
        GeneratorModel generatorModel = null;
        if (StringUtils.isBlank(generatorId)) {
            generatorId = "new";
        }
        if ("new".equals(generatorId)) {
            generatorModel = new GeneratorModel();
        } else {
            generatorModel = GeneratorModel.dao.findById(generatorId);
            if (generatorModel == null) {
                renderHtml("<div class=\"template_error_info\">指定的代码生成器不存在！<div>");
                return;
            }
        }
        setAttr("detail", generatorModel);
        setAttr("template", templateModel);
        render("editGenerator.html");
    }

    /**
     * 代码生成页面
     */
    public void codeGeneratePage() {
        String templateId = getPara("template_id");
        String generatorId = getPara("generator_id");
        GeneratorModel generatorModel = GeneratorModel.dao.findById(generatorId);
        String port = getPara("port");
        setAttr("hasStartedWeb", WebServerService.hasStartedWeb(Integer.parseInt(port)));
        setAttr("generatorModel", generatorModel);
        render("codeGenerate.html");
    }

    /**
     * 文件管理
     */
    @RequiresPermissions("system:generator:temp:edit")
    public void fileMgrPage() {
        String id = getPara("template_id");
        TemplateModel templateModel = null;
        if (id != null) {
            templateModel = TemplateModel.dao.findById(id);
        }
        if (templateModel == null) {
            templateModel = new TemplateModel();
        }
        setAttr("detail", templateModel);
        render("file_mgr.html");
    }

    /**
     * 加载分页列表数据
     */
    @RequiresPermissions("system:generator:temp:list")
    public void list() {
        Map<String, Object> params = getPageParamsPlus();
        Object[] values = getParaValues("values");
        Result result = new Result(false, "未知异常！");
        result.set("code", 400);
        if (StringUtils.isNotBlank(values)) { // formSelects的回显接口
            params.put("template_ids", values);
            result.setListData(Db.find(Db.getSqlPara("sys_template_model.queryPageList", params)));
            result.setSuccess(true);
            result.set("code", 0);
        } else {
            result = Db.paginate("sys_template_model.queryPageList", "sys_template_model.count", params);
            result.set("count", result.get(Result.LIST_TOTAL_KEY));
            result.setSuccess(true);
            result.set("code", 0);
        }
        renderJson(result);
    }

    /**
     * 保存用户信息（新增与修改）
     */
    @RequiresPermissions(value = {"system:generator:temp:add", "system:generator:temp:edit"}, logical = Logical.OR)
    public void save() {
        TemplateModel columnModel = getColumnModel(TemplateModel.class);
        TemplateModel oldModel = null;
        Object id = columnModel.get("template_id");
        if (id != null) {
            oldModel = TemplateModel.dao.findById(id);
        }
        if (oldModel != null) { // 编辑
            columnModel.update();
        } else { // 新增
            columnModel.set("create_datetime", new Date());
            columnModel.set("template_id", IDGenerator.nextId("TemplateModel", IDGenerator.TYPE_SNOWFLAKE));
            columnModel.save();
        }
        SysLogService.service.setSyslog(SysLog.STATUS_SUCCESS, " 保存模板【" + columnModel.getTemplateName() + "】成功！");
        renderJson(new Result(true, "保存模板模型信息成功！"));
    }

    /**
     * 导出模板
     */
//    public void exportPage() {
//        String id = getPara("template_id");
//        TemplateModel templateModel = null;
//        if (id != null) {
//            templateModel = TemplateModel.dao.findById(id);
//        }
//        if (templateModel == null) {
//            templateModel = new TemplateModel();
//        }
//        setAttr("detail", templateModel);
//        render("export.html");
//    }

    /**
     * 复制模板
     */
    @RequiresPermissions(value = {"system:generator:temp:add", "system:generator:temp:edit"}, logical = Logical.OR)
    public void copy() throws IOException {
        String copyTemplateId = getPara("copy_template_id");
        TemplateModel copyTemplate = TemplateModel.dao.findById(copyTemplateId);
        if (copyTemplate == null) { // 编辑
            renderJson(new Result(false, "原模板不存在！"));
            return;
        }
        String newTemplateName = getPara("template_name");
        if (StringUtils.isBlank(newTemplateName)) {
            renderJson(new Result(false, "未批定新的模板名称！"));
            return;
        }
        String templateFilePath = CodeGenerator.getTemplateFilePath(copyTemplate);
        copyTemplate.setTemplateName(newTemplateName);
        // 创建新的模板
        copyTemplate.setTemplateId(IDGenerator.nextId("TemplateModel", IDGenerator.TYPE_SNOWFLAKE));
        copyTemplate.setIsSystem(false);
        copyTemplate.setCreateDatetime(new Date());
        JwebSecurityAccount account = JwebSecurityUtils.getAccount();
        copyTemplate.setAuthor(account.getUid());
        copyTemplate.setOrderNo(10000);
        copyTemplate.setOfficialId(null);
        copyTemplate.save();
        // 复制模板文件
        if (FileUtils.fileExists(templateFilePath)) {
            FileUtils.copy(templateFilePath, CodeGenerator.getTemplateFilePath(copyTemplate));
        }
        SysLogService.service.setSyslog(SysLog.STATUS_SUCCESS, " 复制模板【" + copyTemplate.getTemplateName() + "】成功！");
        renderJson(new Result(true, "复制模板模型信息成功！").set("id", copyTemplate.getTemplateId()));
    }

    /**
     * 导出模板
     */
    public void export() throws IOException {
        TemplateModel columnModel = getColumnModel(TemplateModel.class);
        TemplateModel oldModel = null;
        Object id = columnModel.get("template_id");
        if (id != null) {
            oldModel = TemplateModel.dao.findById(id);
        }
        if (oldModel == null) { // 编辑
            renderJson(new Result(false, "模板不存在！"));
            return;
        }
        // 压缩文件包
        String templateFilePath = CodeGenerator.getTemplateFilePath(oldModel);
        File tempPathFile = new File(templateFilePath);
        String outputPath = tempPathFile.getParent() + File.separator + "output";

        // 清除目录
        String tempDir = outputPath + File.separator + oldModel.getTemplateId();
        FileUtils.delete(tempDir);
        // 创建模板文件目录
        String tempPath = tempDir + File.separator + "template";
        String resPath = tempDir + File.separator + "resource";
        // 创建模板目录
        FileUtils.makeDir(tempPath, true);
        // 复制模板文件
        FileUtils.copy(templateFilePath, tempPath);
        // 创建资源文件夹
        FileUtils.makeDir(resPath, true);
        // 复制资源
        extractTemplateResources(oldModel, resPath);

        // 创建模板信息文件
        File jsonFile = FileUtils.write(outputPath + File.separator + oldModel.getTemplateId() + File.separator + "main.json", gson.toJson(oldModel), Charset.forName("UTF-8"));
        // 创建模板信息文件
        File versionFile = FileUtils.write(outputPath + File.separator + oldModel.getTemplateId() + File.separator + "version", "1.0", Charset.forName("UTF-8"));

        // 打包文件
        String downloadName = oldModel.getTemplateName() + "-v" + oldModel.getVersion();
        if (oldModel.getOfficialId() != null) {
            downloadName = "Official-" + downloadName;
        } else {
            downloadName = "Custom-" + downloadName;
        }
        File zip = ZipUtils.getInstance().zip(new File[]{new File(tempPath), new File(resPath), jsonFile, versionFile}, outputPath + File.separator + downloadName + ".zip");
        renderFile(zip);
    }

    /**
     * 提供模板文件中的图片资源文件到指定目录
     *
     * @param oldModel
     * @param targetPath
     * @throws IOException
     */
    @NotAction
    private void extractTemplateResources(TemplateModel oldModel, String targetPath) throws IOException {
        String thumb = oldModel.getThumb();
        List<SysFile> list = new ArrayList<>();
        if (thumb != null) {
            Map[] files = gson.fromJson(thumb, new TypeToken<Map[]>() {
            }.getType());
            if (files != null) {
                for (Map file : files) {
                    String fileId = (String) file.get("file_id");
                    SysFile sysFile = SysFile.dao.findById(fileId);
                    if (sysFile != null) {
                        list.add(sysFile);
                    }
                }
            }
        }
        String desc = oldModel.getDesc();
        Pattern regex = Pattern.compile("/file/download\\?fileId=(.*?)\"");
        Matcher regexMatcher = regex.matcher(desc);
        while (regexMatcher.find()) {
            String fileId = regexMatcher.group(1);
            SysFile sysFile = SysFile.dao.findById(fileId);
            if (sysFile != null) {
                list.add(sysFile);
            }
        }
        if (list.size() > 0) {
            String webRootPath = PathKit.getWebRootPath();
            String uploadDirPath = FileService.service.getUploadPath();
            for (SysFile sysFile : list) {
                String filePath = uploadDirPath + File.separator + sysFile.getFilePath();
                FileUtils.copy(filePath, targetPath + File.separator + sysFile.getFilePath());
            }
            // 写入资源文件信息
            FileUtils.write(targetPath + File.separator + "main.json", gson.toJson(list), Charset.forName("UTF-8"));
        }

    }

    /**
     * 导入模板包
     */
    @RequiresPermissions(value = {"system:generator:temp:add", "system:generator:temp:edit"}, logical = Logical.OR)
    public void importTemp() {
        UploadFile file = null;
        try {
            file = getFile();
        } catch (Exception exception) {
            exception.printStackTrace();
        }
        String unZipPath = getPara("unZipPath");
        if (unZipPath == null) {
            if (file == null) {
                renderJson(new Result(false, "未上传模板文件包！"));
                return;
            }
            // 1.解压
            unZipPath = file.getFile().getParent() + File.separator + IDGenerator.nextId("file", IDGenerator.TYPE_SNOWFLAKE);
            String zipFilePath = file.getFile().getAbsolutePath();
            try {
                FileUtils.delete(unZipPath);// 删除目录
                ZipUtils.getInstance().unZip(zipFilePath, unZipPath);
                FileUtils.delete(zipFilePath);
            } catch (IOException e) {
                renderJson(new Result(false, "解压模板包异常！").set("error", e.getMessage()));
                return;
            }
        }
        // 2.解析json,
        String version = null;
        try {
            version = FileUtils.readText(unZipPath + File.separator + "version", "", Charset.forName("UTF-8"));
        } catch (IOException e) {
            renderJson(new Result(false, "读取模板包版本文件version异常！").set("error", e.getMessage()));
            return;
        }
        if (!"1.0".equalsIgnoreCase(version)) {
            renderJson(new Result(false, "不支持模板包版本：" + version));
            return;
        }
        // 2.解析json,
        String mainJson = null;
        try {
            mainJson = FileUtils.readText(unZipPath + File.separator + "main.json", "", Charset.forName("UTF-8"));
        } catch (IOException e) {
            renderJson(new Result(false, "读取模板包信息文件main.json异常！").set("error", e.getMessage()));
            return;
        }
        TemplateModel templateModel = gson.fromJson(mainJson, TemplateModel.class);
        // 3.判断模板版本
        TemplateModel officialTemplate = null;
        if (templateModel.getOfficialId() != null && !"false".equals(getPara("confirm"))) {
            officialTemplate = TemplateModel.dao.findFirst("select * from sys_template_model where official_id = ?", templateModel.getOfficialId());
            if (officialTemplate != null) {
                int compareVersion = compareVersion(officialTemplate.getVersion(), templateModel.getVersion());
                renderJson(new Result(false, "官方模板包已存在！")
                        .set("oldVersion", officialTemplate.getVersion())
                        .set("newVersion", templateModel.getVersion())
                        .set("path", unZipPath)
                        .set("templateName", templateModel.getTemplateName())
                        .set("confirm", compareVersion > 0 ? "rollback" : compareVersion == 0 ? "overwrite" : "update")
                );
                return;
            }
        }
        // 4.插入db,更新db,插入文件db
        String uploadDirPath = FileService.service.getUploadPath();
        String resourcePath = unZipPath + File.separator + "resource";
        String resJsonFilePath = resourcePath + File.separator + "main.json";
        if (FileUtils.fileExists(resJsonFilePath)) {
            String resourcesJson = null;
            try {
                resourcesJson = FileUtils.readText(resJsonFilePath, "", Charset.forName("UTF-8"));
            } catch (IOException e) {
                renderJson(new Result(false, "读取模板包资源文件main.json异常！").set("error", e.getMessage()));
                return;
            }
            SysFile[] sysFiles = gson.fromJson(resourcesJson, new TypeToken<SysFile[]>() {
            }.getType());
            // 插入资源文件信息
            for (SysFile sysFile : sysFiles) {
                SysFile oldSysFile = SysFile.dao.findById(sysFile.getFileId());
                if (oldSysFile != null) {
                    sysFile._setOrPut(sysFile);
                    sysFile.update();
                } else {
                    sysFile.save();
                }
            }
            // 复制资源文件
            File resourceFile = new File(resourcePath);
            String[] resources = resourceFile.list(new FilenameFilter() {
                @Override
                public boolean accept(File dir, String name) {
                    return !name.equalsIgnoreCase("main.json");
                }
            });
            for (String filePath : resources) {
                try {
                    FileUtils.copy(resourcePath + File.separator + filePath, uploadDirPath + filePath);
                } catch (IOException e) {
                    renderJson(new Result(false, "复制模板资源文件异常！").set("error", e.getMessage()));
                    return;
                }
            }
        }
        // 5.插入模板数据库信息
        if (templateModel.getOfficialId() != null) {
            officialTemplate = TemplateModel.dao.findFirst("select * from sys_template_model where official_id = ?", templateModel.getOfficialId());
            if (officialTemplate != null) {
                templateModel._setOrPut(templateModel);
                templateModel.update();
            } else {
                templateModel.save();
            }
        } else {
            templateModel.setTemplateId(IDGenerator.nextId("TemplateModel", IDGenerator.TYPE_SNOWFLAKE));
            templateModel.save();
        }
        // 导入模板文件
        try {
            FileUtils.move(unZipPath + File.separator + "template", CodeGenerator.getTemplateFilePath(templateModel));
        } catch (IOException e) {
            renderJson(new Result(false, "导入模板文件异常！").set("error", e.getMessage()));
            return;
        }
        SysLogService.service.setSyslog(SysLog.STATUS_SUCCESS, " 导入模板【" + templateModel.getTemplateName() + "】成功！");
        renderJson(new Result(true, "导入模板成功！").set("id", templateModel.getTemplateId()));
        FileUtils.delete(unZipPath);
    }

    /**
     * 删除记录
     */
    @RequiresPermissions("system:generator:temp:del")
    public void delete() {
        String[] ids = getParaValues("ids");
        if (ids == null || ids.length <= 0) {
            renderJson(new Result(true, "删除成功！"));
            return;
        }
        boolean b = true;
        for (String id : ids) {
            TemplateModel templateModel = TemplateModel.dao.findById(id);
            if (templateModel != null) {
                if (!templateModel.isSystem()) {
                    b = b & TemplateModel.dao.deleteById(id);
                    if (b) {
                        // 删除文件
                        String templateFilePath = CodeGenerator.getTemplateFilePath(templateModel);
                        FileUtils.delete(templateFilePath);
                    }
                } else {
                    renderJson(new Result(false, "系统模板无法被删除！"));
                    return;
                }
            }
        }
        SysLogService.service.setSyslog(b ? SysLog.STATUS_SUCCESS : SysLog.STATUS_FAILURE, "删除模板【id:" + StringUtils.join(ids, ",") + "】" + (b ? "成功" : "失败") + " !");
        renderJson(new Result(b, b ? "删除成功！" : "删除失败！"));
    }


    /**
     * XCE对象的api接口
     *
     * @throws IOException
     */
    public void xceApi() throws IOException {
        if (isParaBlank("templateId")) {
            renderJson(new Result(false, "模板编号不存在！"));
            return;
        }
        String oper = getPara("oper");
        if (isParaBlank("oper")) {
            renderJson(new Result(false, "未知操作！"));
            return;
        }
        TemplateModel templateModel = TemplateModel.dao.findById(getPara("templateId"));
        if (templateModel == null) {
            renderJson(new Result(false, "模板不存在！"));
            return;
        }
        switch (oper) {
            case "list":
                listFile(templateModel);
                break;
            case "create":
                createFile(templateModel);
                break;
            case "save":
                saveFile(templateModel);
                break;
            case "move":
                moveFile(templateModel);
                break;
            case "copy":
                copyFile(templateModel);
                break;
            case "delete":
                deleteFile(templateModel);
                break;
            case "import":
                importFile(templateModel);
                break;
            case "content":
                download(templateModel);
                break;

        }
    }

    @NotAction
    private String fixPath(String path) {
        if (StringUtils.isBlank(path)) {
            return path;
        }
        if (path.indexOf("~") >= 0 || path.indexOf("..") >= 0) {
            throw new ParameterValidationException("路径不正确！");
        }
        path = path.replace("..", "").replace("//", "/");
        if (!path.startsWith("/")) {
            path = "/" + path;
        }
        return path;
    }

    /**
     * 删除文件
     *
     * @param templateModel
     */
    @NotAction
    private void deleteFile(TemplateModel templateModel) {
        if (templateModel.getOfficialId() != null) {
            renderJson(new Result(false, "官方模板无法删除文件！"));
            return;
        }
        String path = fixPath(getPara("path"));
        if (StrKit.isBlank(path)) {
            renderJson(new Result(false, "路径不能为空！"));
            return;
        }
        String templateFilePath = CodeGenerator.getTemplateFilePath(templateModel);
        FileUtils.delete(templateFilePath + path);
        renderJson(new Result(true, "删除成功！"));
    }

    /**
     * 导入文件
     *
     * @param templateModel
     */
    @NotAction
    private void importFile(TemplateModel templateModel) throws IOException {
        if (templateModel.getOfficialId() != null) {
            renderJson(new Result(false, "官方模板无法导入文件！"));
            return;
        }
        List<UploadFile> files = getFiles();
        String path = fixPath(getPara("path"));
        if (StrKit.isBlank(path)) {
            renderJson(new Result(false, "路径不能为空！"));
            return;
        }
        if (files.size() > 0) {
            String templateFilePath = CodeGenerator.getTemplateFilePath(templateModel);
            String target = templateFilePath + path;
            target = target.endsWith("/") ? target : target + "/";
            for (UploadFile file : files) {
                FileUtils.move(file.getFile().getAbsolutePath(), target + file.getFileName());
            }
        }
        renderJson(new Result(true, "导入成功！"));
    }

    /**
     * 复制文件
     *
     * @param templateModel
     */
    @NotAction
    private void copyFile(TemplateModel templateModel) {
        if (templateModel.getOfficialId() != null) {
            renderJson(new Result(false, "官方模板无法复制文件！"));
            return;
        }
        String from = fixPath(getPara("from"));
        String to = fixPath(getPara("to"));
        if (StrKit.isBlank(from)) {
            renderJson(new Result(false, "源路径不能为空！"));
            return;
        }
        if (StrKit.isBlank(to)) {
            renderJson(new Result(false, "目标路径不能为空！"));
            return;
        }
        try {
            String templateFilePath = CodeGenerator.getTemplateFilePath(templateModel);
            FileUtils.copy(templateFilePath + from, templateFilePath + to);
        } catch (IOException e) {
            renderJson(new Result(false, e.getMessage()));
            return;
        }
        renderJson(new Result(true, "复制成功！"));
    }

    /**
     * 移动文件
     *
     * @param templateModel
     */
    @NotAction
    private void moveFile(TemplateModel templateModel) {
        if (templateModel.getOfficialId() != null) {
            renderJson(new Result(false, "官方模板无法移动文件！"));
            return;
        }
        String from = fixPath(getPara("from"));
        String to = fixPath(getPara("to"));
        if (StrKit.isBlank(from)) {
            renderJson(new Result(false, "源路径不能为空！"));
            return;
        }
        if (StrKit.isBlank(to)) {
            renderJson(new Result(false, "目标路径不能为空！"));
            return;
        }
        try {
            String templateFilePath = CodeGenerator.getTemplateFilePath(templateModel);
            FileUtils.move(templateFilePath + from, templateFilePath + to);
        } catch (IOException e) {
            renderJson(new Result(false, e.getMessage()));
            return;
        }
        renderJson(new Result(true, "移动成功！"));
    }

    /**
     * 创建新文件
     *
     * @param templateModel
     */
    @NotAction
    private void createFile(TemplateModel templateModel) {
        if (templateModel.getOfficialId() != null) {
            renderJson(new Result(false, "官方模板无法创建文件！"));
            return;
        }
        String path = fixPath(getPara("path"));
        if (StrKit.isBlank(path)) {
            renderJson(new Result(false, "保存路径不正确！"));
            return;
        }
        try {
            String newFilePath = CodeGenerator.getTemplateFilePath(templateModel) + path;
            File newFile = new File(newFilePath);
            // 创建目录
            FileUtils.makeDir(newFile.getParent(), true);
            // 创建文件
            FileUtils.write(newFilePath, "", Charset.forName("UTF-8"));
        } catch (IOException e) {
            renderJson(new Result(false, e.getMessage()));
            return;
        }
        renderJson(new Result(true, "创建文件成功！"));
    }

    /**
     * 上传保存文件内容
     *
     * @param templateModel
     * @throws NoSuchFileException
     */
    @NotAction
    private void saveFile(TemplateModel templateModel) throws IOException {
        if (templateModel.getOfficialId() != null) {
            renderJson(new Result(false, "官方模板无法保存文件！"));
            return;
        }
        UploadFile file = getFile();
        String path = fixPath(getPara("path"));
        if (StrKit.isBlank(path)) {
            renderJson(new Result(false, "保存路径不正确！"));
            return;
        }
        boolean move = FileUtils.move(file.getFile().getAbsolutePath(), CodeGenerator.getTemplateFilePath(templateModel) + path);
        renderJson(new Result(move, "保存文件" + (move ? "成功！" : "失败！")));
    }


    /**
     * 文件列表
     */
    @NotAction
    public void listFile(TemplateModel templateModel) {
        List fileList = readFileList(new File(CodeGenerator.getTemplateFilePath(templateModel)), "");
        Result result = new Result(true);
        result.setData(fileList);
        renderJson(result);
    }

    /**
     * 递归加载文件列表
     *
     * @param codePath
     * @return
     */
    @NotAction
    private List readFileList(File codePath, String parentPath) {
        List list = new ArrayList();
        File[] files = codePath.listFiles();
        if (files != null) {
            for (File file : files) {
                String filePath = parentPath + "/" + file.getName();
                Map<String, Object> fileInfo = MapUtils.of("title", file.getName(),
                        "spread", file.isDirectory(),
                        "path", filePath,
                        "id", filePath
                );
                fileInfo.put("isFolder", file.isDirectory());
                if (file.isDirectory()) {
                    fileInfo.put("children", readFileList(file, filePath));
                }
                list.add(fileInfo);
            }
        }
        return list;
    }

    /**
     * 文件下载接口
     *
     * @throws IOException
     */
    @NotAction
    public void download(TemplateModel templateModel) throws IOException {
        Result result = new Result(false);
        String templateId = getPara("templateId");
        String path = fixPath(getPara("path"));
        File downFile = new File(CodeGenerator.getTemplateFilePath(templateModel) + path);
        if (!downFile.exists()) {
            renderJson(new Result(false, "找不到文件！"));
            return;
        }
        render(new Render() {
            private static final String DEFAULT_CONTENT_TYPE = "application/octet-stream;";

            @Override
            public void render() {
                response.setHeader("Accept-Ranges", "bytes");
                //String newReportName  = reportName == null?"安全分析统计报告":reportName;
                String downloadFileNameHeader = ResponseUtils.getDownloadFileNameHeader(getRequest(), downFile.getName());
                response.setHeader("Content-disposition", downloadFileNameHeader);
                ServletOutputStream outputStream = null;
                InputStream fis = null;
                try {
                    outputStream = response.getOutputStream();
                    fis = new BufferedInputStream(new FileInputStream(downFile));
                    byte[] cache = new byte[1024];
                    int count = 0;
                    while ((count = fis.read(cache)) != -1) {
                        outputStream.write(cache, 0, count);//将缓冲区的数据输出到浏览器
                    }
                    outputStream.flush();
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    if (outputStream != null) {
                        try {
                            outputStream.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    if (fis != null) {
                        try {
                            fis.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }

        });
    }

}